/**
 * @file    inf_solenoid_valve.c
 * @author  yhy
 * @brief   电磁阀硬件接口层源文件，用于控制电磁阀的开关
 * @version 1.03
 * @date    2025-07-20
 *
 * @copyright Copyright (c) 2025
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-07-20     yhy          the first version V1.00
 * 2025-08-19     yhy          修改缓升缓降逻辑, 加入了单独控制单步步进时间 V1.01
 * 2025-08-21     yhy          新增电磁阀动态占空比，会随着电压的变化而变化 v1.02
 * 2025-09-15     yhy          - 修复了缓升缓降12V延时bug
 *                             - 修改电磁阀缓升缓降控制逻辑 V1.03
 */
#include "inf_solenoid_valve.h"

#include "common_debug.h"
#include "inf_74hc595.h"

static result_e inf_solenoid_valve_validate_channel(solenoid_valve_channel_e channel);
static void     inf_solenoid_valve_process_ramp_up(solenoid_valve_t *valve);
static void     inf_solenoid_valve_process_ramp_down(solenoid_valve_t *valve);
static void     inf_solenoid_valve_set_duty_cycle(solenoid_valve_channel_e channel, uint32_t duty_cycle);

/* 缓升序列 */
static const voltage_level_step_t ramp_up_sequence[] = {
    { VOLTAGE_LEVEL_2V, 20 },   { VOLTAGE_LEVEL_4V, 20 },  { VOLTAGE_LEVEL_6V, 20 },
    { VOLTAGE_LEVEL_8V, 20 },   { VOLTAGE_LEVEL_10V, 20 }, { VOLTAGE_LEVEL_12V, 200 },
    { VOLTAGE_LEVEL_6P5V, 20 },
};

/* 缓降序列 */
static const voltage_level_step_t ramp_down_sequence[] = {
    { VOLTAGE_LEVEL_4V, 20 },
    { VOLTAGE_LEVEL_2V, 20 },
    { VOLTAGE_LEVEL_0V, 20 },
};

#define RAMP_UP_STEPS   (sizeof(ramp_up_sequence) / sizeof(ramp_up_sequence[0]))
#define RAMP_DOWN_STEPS (sizeof(ramp_down_sequence) / sizeof(ramp_down_sequence[0]))

/* 电磁阀控制系统实例 */
solenoid_valve_system_t valve_system;

/* 电压补偿系数，基于12V供电, 当电压变化时系数也随之改变 */
float voltage_comp_factor = 1.0f;

/**
 * @brief 初始化电磁阀控制系统
 *
 * @return result_e 初始化结果, 成功返回RESULT_STATUS_OK, 失败返回其他
 */
result_e inf_solenoid_valve_init(void)
{
    result_e result = inf_74hc595_init();
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    /* 初始化系统参数 */
    valve_system.system_enable = false;

    /* 初始化所有阀门参数 */
    for (uint8_t i = 0; i < SOLENOID_VALVE_CH_MAX; ++i) {
        valve_system.valve_list[i].state         = SOLENOID_VALVE_STATE_DISABLED;
        valve_system.valve_list[i].target_enable = false;
        valve_system.valve_list[i].current_duty  = VOLTAGE_LEVEL_0V;
        valve_system.valve_list[i].step_idx      = 0U;
        valve_system.valve_list[i].step_delay    = 0U;
    }

    /* 初始关闭所有阀门, 为0V输出 */
    for (uint8_t i = 0; i < SOLENOID_VALVE_CH_MAX; ++i) {
        inf_solenoid_valve_set_duty_cycle((solenoid_valve_channel_e)i, VOLTAGE_LEVEL_0V);
    }

    return RESULT_STATUS_OK;
}

/**
 * @brief 设置指定阀门使能状态
 *
 * @param channel       阀门通道
 * @param enable        使能状态
 * @return result_e     设置结果, 成功返回RESULT_STATUS_OK, 失败返回其他
 */
result_e inf_solenoid_valve_set_enable(solenoid_valve_channel_e channel, bool enable)
{
    result_e result = inf_solenoid_valve_validate_channel(channel);
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    /* 判断电磁阀系统是否使能 */
    if (!valve_system.system_enable) {
        return RESULT_STATUS_ERROR;
    }

    solenoid_valve_t *valve = &valve_system.valve_list[channel];

    /* 如果目标状态没有改变, 直接返回 */
    if (valve->target_enable == enable) {
        return RESULT_STATUS_OK;
    }

    valve->target_enable = enable;
    valve->step_idx      = 0U;
    valve->step_delay    = 0U;

    if (enable) {
        /* 开始缓升过程 */
        valve->state = SOLENOID_VALVE_STATE_RAMP_UP;
    }
    else {
        /* 开始缓降过程 */
        valve->state = SOLENOID_VALVE_STATE_RAMP_DOWN;
    }

    return RESULT_STATUS_OK;
}

/**
 * @brief 设置所有阀门使能状态
 *
 * @param   enable      使能状态
 * @return  result_e    设置结果, 成功返回RESULT_STATUS_OK, 失败返回其他
 */
result_e inf_solenoid_valve_set_all_valves(bool enable)
{
    for (uint8_t i = 0; i < SOLENOID_VALVE_CH_MAX; ++i) {
        result_e result = inf_solenoid_valve_set_enable((solenoid_valve_channel_e)i, enable);
        if (result != RESULT_STATUS_OK) {
            return result;
        }
    }

    return RESULT_STATUS_OK;
}

/**
 * @brief 设置系统总使能
 *
 * @param   enable      系统使能状态
 * @return  result_e    设置结果, 成功返回RESULT_STATUS_OK, 失败返回其他
 */
result_e inf_solenoid_valve_set_system_enable(bool enable)
{
    valve_system.system_enable = enable;

    /* 如果系统失能, 则立即关闭所有阀门 */
    if (!enable) {
        for (uint8_t i = 0; i < SOLENOID_VALVE_CH_MAX; ++i) {
            valve_system.valve_list[i].state         = SOLENOID_VALVE_STATE_DISABLED;
            valve_system.valve_list[i].target_enable = false;
            valve_system.valve_list[i].current_duty  = VOLTAGE_LEVEL_0V;
            inf_solenoid_valve_set_duty_cycle((solenoid_valve_channel_e)i, VOLTAGE_LEVEL_0V);
        }
    }

    return RESULT_STATUS_OK;
}

/**
 * @brief 处理电磁阀的开与关, 包括缓升与缓降, 放在timer中调用（5ms）
 *
 */
void inf_solenoid_valve_ctrl_handle(void)
{
    if (!valve_system.system_enable) {
        return;
    }

    for (uint8_t i = 0; i < SOLENOID_VALVE_CH_MAX; ++i) {
        solenoid_valve_t *valve = &valve_system.valve_list[i];

        switch (valve->state) {
        case SOLENOID_VALVE_STATE_RAMP_UP:
            inf_solenoid_valve_process_ramp_up(valve);
            inf_solenoid_valve_set_duty_cycle((solenoid_valve_channel_e)i, valve->current_duty);
            break;
        case SOLENOID_VALVE_STATE_RAMP_DOWN:
            inf_solenoid_valve_process_ramp_down(valve);
            inf_solenoid_valve_set_duty_cycle((solenoid_valve_channel_e)i, valve->current_duty);
            break;
        }
    }
}

/**
 * @brief 处理缓升过程
 *
 * @param valve 阀门参数指针
 */
static void inf_solenoid_valve_process_ramp_up(solenoid_valve_t *valve)
{
    /* 如果刚开始缓升或刚切换到新等级，立即设置电压等级 */
    if (valve->step_delay == 0U) {
        valve->current_duty = ramp_up_sequence[valve->step_idx].voltage_level;
    }

    valve->step_delay += SOLENOID_VALVE_STEP_CYCLE;

    /* 检查当前电压等级是否已持续足够时间 */
    if (valve->step_delay >= ramp_up_sequence[valve->step_idx].step_time_ms) {
        valve->step_delay = 0U;
        ++valve->step_idx;

        /* 缓升完成, 进入使能状态 */
        if (valve->step_idx >= RAMP_UP_STEPS) {
            valve->state        = SOLENOID_VALVE_STATE_ENABLED;
            valve->current_duty = VOLTAGE_LEVEL_6P5V; // 保持在6.5V
        }
    }
}

/**
 * @brief 处理缓降过程
 *
 * @param valve 阀门参数指针
 */
static void inf_solenoid_valve_process_ramp_down(solenoid_valve_t *valve)
{
    /* 如果刚开始缓降或刚切换到新等级，立即设置电压等级 */
    if (valve->step_delay == 0U) {
        valve->current_duty = ramp_down_sequence[valve->step_idx].voltage_level;
    }

    valve->step_delay += SOLENOID_VALVE_STEP_CYCLE;

    /* 检查当前电压等级是否已持续足够时间 */
    if (valve->step_delay >= ramp_down_sequence[valve->step_idx].step_time_ms) {
        valve->step_delay = 0U;
        ++valve->step_idx;

        /* 缓降完成, 进入失能状态 */
        if (valve->step_idx >= RAMP_DOWN_STEPS) {
            valve->state        = SOLENOID_VALVE_STATE_DISABLED;
            valve->current_duty = VOLTAGE_LEVEL_0V; // 保持在0V
        }
    }
}

/**
 * @brief 设置阀门占空比并更新74HC595输出
 *
 * @param channel       阀门通道
 * @param duty_cycle    占空比
 */
static void inf_solenoid_valve_set_duty_cycle(solenoid_valve_channel_e channel, uint32_t duty_cycle)
{
    /* 根据实际电压计算实际占空比 */
    int8_t real_duty_cycle = (int8_t)(duty_cycle * voltage_comp_factor);
    if (real_duty_cycle < 0) {
        real_duty_cycle = 0;
    }
    else if (real_duty_cycle > 100) {
        real_duty_cycle = 100;
    }

    inf_74hc595_set_duty((sr_74hc595_channel_e)channel, real_duty_cycle);
}

/**
 * @brief 验证通道参数
 *
 * @param   channel     阀门通道
 * @return  result_e    验证结果, 成功返回RESULT_STATUS_OK, 失败返回其他
 */
static result_e inf_solenoid_valve_validate_channel(solenoid_valve_channel_e channel)
{
    if (channel >= SOLENOID_VALVE_CH_MAX) {
        return RESULT_STATUS_INVALID_PARAM;
    }

    return RESULT_STATUS_OK;
}
